
const express = require("express");
const updateCompiler = require('./utils/updateCompiler');
const webpackDevMiddleware = require('../../webpack-dev-middleware/index');
const http = require("http");
const WebsocketServer = require("socket.io");

class Server {
    constructor(compiler,devServerArgs) {
        this.sockets=[] //服务器连接的客户端
        this.compiler = compiler;
        this.devServerArgs = devServerArgs;
        updateCompiler(compiler); //更新编译器,修改入口，添加了两个文件
        this.setupHooks();//开始启动webpack编译,添加webpack的done事件回调，在编译完成后会向浏览器发送消息
        this.setupApp(); //创建express应用app
        this.routes(); 
        this.setupDevMiddleware();//建立开发中间件
        this.createServer(); //创建http服务器
        this.createSocketServer(); //创建SocketServer
    }

    setupHooks(){
        // 监听编译成功的事件 stats里面保存着编译成功后的描述(modules,chunks,files,assets,entries)
        this.compiler.hooks.done.tap('webpack-dev-server',(stats)=>{
            console.log("stats.hash", stats.hash);
            // 以后每次新的编译成功后，都要向客户端发送新的hash值和ok
            this.sockets.forEach((socket)=>{
                socket.emit('hash', stats.hash);
                socket.emit('ok');
            })
            this._stats = stats;//保存上一次的stats信息
        });
    }

    setupApp(){
        //this.app并不是一个http服务，它本身其实只是一个路由中间件
        this.app = express();
    }
    routes(){
        if(this.devServerArgs.contentBase){
            //此目录将会成为静态文件根目录
           this.app.use(express.static(this.devServerArgs.contentBase));
        }
    }
    setupDevMiddleware(){
        this.middleware = webpackDevMiddleware(this.compiler);
        this.app.use(this.middleware);
    }
    createServer() {
        this.server = http.createServer(this.app);
    }
    createSocketServer(){
        // websocket通信之前需要握手，握手的时候需要用http协议
        const io = WebsocketServer(this.server)
        // 监听客户端的连接
        io.on('connection',(socket)=>{
            console.log("client connected");
            //  
            this.sockets.push(socket)
            // 监控客户端断开事件
            socket.on('disconnect',(socket)=>{
                let index = this.sockets.indexOf(socket)
                this.sockets = this.sockets.splice(index, 1);
            })
            // 如果以前已经编译过了，就把上一次的hash值和ok发给客户端
            if(this._stats){
                socket.emit('hash',this._stats.hash)
                socket.emit('ok')
            }
        })
    }
    listen(port, host = "localhost", callback = ()=>{}){
        this.server.listen(port,host,callback)
    }
}
module.exports = Server


/**
this.app.listen(); 
var server = http.createServer(this);
return server.listen.apply(server, arguments);
 */